//
//	NeutriumJS Steam
//	https://github.com/NativeDynamics/NeutriumJS.Steam
//
//	Copyright 2015, Native Dynamics
//	https://neutrium.net
//
//	Licensed under the Creative Commons Attribution 4.0 International
//	http://creativecommons.org/licenses/by/4.0/legalcode
//
(function (root, factory) {
    "use strict";

	if(typeof define === "function" && define.amd)
	{
		define('NeutriumJS/thermo/IAPWS97/PS', ['NeutriumJS/thermo/IAPWS97', 'NeutriumJS/thermo/IAPWS97/PT'], factory);
	}
	else if (typeof exports === "object" && module.exports)
	{
		module.exports = factory(require('NeutriumJS.thermo.IAPWS97'), require('NeutriumJS.thermo.IAPWS97.PT'));
	}
	else
	{
		root.NeutriumJS = root.NeutriumJS || {};
		root.NeutriumJS.thermo = root.NeutriumJS.thermo || {};
		root.NeutriumJS.thermo.IAPWS97 = root.NeutriumJS.thermo.IAPWS97 || {};
		root.NeutriumJS.thermo.IAPWS97.PS = factory(root.NeutriumJS.thermo.IAPWS97, root.NeutriumJS.thermo.IAPWS97.PT);
	}
}(this, function (NS, PT) {
	"use strict";

	// Private members
	var R = NS.CONST('R'),
		PS = {
			solve : solve,
			// Exposed for testing
			r3A_PS_V : r3A_PS_V,
			r3B_PS_V : r3B_PS_V
		};

	return PS;

	//
	//	Comments : Determines which IAPWS-IF97 region a pressure and entropy combination lie in.
	//
	//	@param P is the pressure of the water in mega Pascals
	//	@param s is the entropy in kJ . K^-1 . kg^1
	//
	function solve(P, s)
	{
		var region = findRegion_PS(P,s),
			result = null;

		switch(region)
		{
			case 1	: result = r1_PS(P, s); break;
			case 2  : result = r2_PS(P, s); break;
			case 3  : result = r3_PS(P, s); break;
			//case 4  : result = R4_PS(P, s); break;
			default : throw new NS.Exception();
		}

		return result;
	}

	//
	//	Comments : Determines which IAPWS-IF97 region a pressure and entropy combination lie in.
	//
	//	@param P is the pressure of the water in mega Pascals
	//	@param s is the entropy in kJ/kg
	//
	function findRegion_PS(P, s)
	{
		var r = PT.r5(P, NS.CONST('R5_MAX_T'));

		if(P >= NS.CONST('MIN_P') && P <= NS.CONST('MAX_P') && s >= NS.CONST('MIN_S') && s <= r.s)
		{
			r = PT.r2(P, NS.CONST('R5_MIN_T'));

			if(s > r.s && P <= NS.CONST('R5_MAX_P'))
			{
				return 5;
			}

			if(P > NS.CONST('B23_MIN_P'))
			{
				r = PT.r2(P, PT.b23_P_T(P));

				if(s > r.s)
				{
					return 2;
				}

				r = PT.r3(P, NS.CONST('R3_MIN_T'));

				if(s > r.s)
				{
					return 3;
				}
			}

			r = PT.r1(P, PT.r4_P_Tsat(P));

			if(P <= NS.CONST('B23_MIN_P') && s > r.s)
			{
				return 2;
			}

			r = PT.r1(P, NS.CONST('MIN_T'));

			if(s >= r.s)
			{
				return 1;
			}
		}

		return -1;
	}

	//
	//	Backwards equations for region 1 (P and s given)
	//
	function r1_PS(P, s)
	{
		var T = r1_PS_T(P,s);

		return PT.r1(P,T);
	}

	function r1_PS_T(P, s)
	{
		var R1_PS_I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4],
			R1_PS_J = [0, 1, 2, 3, 11, 31, 0, 1, 2, 3, 12, 31, 0, 1, 2, 9, 31, 10, 32, 32],
			R1_PS_N = [174.78268058307, 34.806930892873, 6.5292584978455, 0.33039981775489, -1.9281382923196E-7, -2.4909197244573E-23, -0.26107636489332, 0.22592965981586, -0.064256463395226, 0.0078876289270526, 3.5672110607366E-10, 1.7332496994895E-24, 0.00056608900654837, -0.00032635483139717, 0.000044778286690632, -5.1322156908507E-10, -4.2522657042207E-26, 2.6400441360689E-13, 7.8124600459723E-29, -3.0732199903668E-31],
			pi = P,
			sig = s,
			T = 0;

		for(var i = 0; i < 20; i++)
		{
			var N = R1_PS_N[i],
				I = R1_PS_I[i],
				J = R1_PS_J[i];

			T += N*Math.pow(pi,I)*Math.pow(sig+2,J);
		}

		return T;
	}

	//
	//	Backwards equation for region 2 (P and s given)
	//
	function r2_PS(P, s)
	{
		var T = r2_PS_T(P,s);

		return PT.r2(P,T);
	}

	function r2_PS_T(P, s)
	{
		var T;

		if(P <= NS.CONST('R2_CRT_P'))
		{
			T = r2A_PS_T(P, s);
		}
		else
		{
			if(s >= NS.CONST('R2_CRT_S'))
			{
				T = r2B_PS_T(P, s);
			}
			else
			{
				T = r2C_PS_T(P, s);
			}
		}

		return T;
	}

	function r2A_PS_T(P, s)
	{
		var R2A_PS_I = [-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.25, -1.25, -1.25, -1, -1, -1, -1, -1, -1, -0.75, -0.75, -0.5, -0.5, -0.5, -0.5, -0.25, -0.25, -0.25, -0.25, 0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.75, 0.75, 0.75, 0.75, 1, 1, 1.25, 1.25, 1.5, 1.5],
			R2A_PS_J = [-24, -23, -19, -13, -11, -10, -19, -15, -6, -26, -21, -17, -16, -9, -8, -15, -14, -26, -13, -9, -7, -27, -25, -11, -6, 1, 4, 8, 11, 0, 1, 5, 6, 10, 14, 16, 0, 4, 9, 17, 7, 18, 3, 15, 5, 18],
			R2A_PS_N = [-392359.83861984, 515265.7382727, 40482.443161048, -321.93790923902, 96.961424218694, -22.867846371773, -449429.14124357, -5011.8336020166, 0.35684463560015, 44235.33584819, -13673.388811708, 421632.6027864, 22516.925837475, 474.42144865646, -149.31130797647, -197811.26320452, -23554.39947076, -19070.616302076, 55375.669883164, 3829.3691437363, -603.91860580567, 1936.3102620331, 4266.064369861, -5978.0638872718, -704.01463926862, 338.36784107553, 20.862786635187, 0.033834172656196, -0.000043124428414893, 166.53791356412, -139.86292055898, -0.78849547999872, 0.072132411753872, -0.0059754839398283, -0.000012141358953904, 2.3227096733871E-7, -10.538463566194, 2.0718925496502, -0.072193155260427, 2.074988708112E-7, -0.018340657911379, 2.9036272348696E-7, 0.21037527893619, 0.00025681239729999, -0.012799002933781, -8.2198102652018E-6],
			pi = P,
			sig = s/2,
			T = 0;

		for(var i = 0; i < 46; i++)
		{
			var N = R2A_PS_N[i],
				I = R2A_PS_I[i],
				J = R2A_PS_J[i];

			T += N*Math.pow(pi,I)*Math.pow(sig-2,J);
		}

		return T;
	}

	function r2B_PS_T(P, s)
	{
		var R2B_PS_I = [-6, -6, -5, -5, -4, -4, -4, -3, -3, -3, -3, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5],
			R2B_PS_J = [0, 11, 0, 11, 0, 1, 11, 0, 1, 11, 12, 0, 1, 6, 10, 0, 1, 5, 8, 9, 0, 1, 2, 4, 5, 6, 9, 0, 1, 2, 3, 7, 8, 0, 1, 5, 0, 1, 3, 0, 1, 0, 1, 2],
			R2B_PS_N = [316876.65083497, 20.864175881858, -398593.99803599, -21.816058518877, 223697.85194242, -2784.1703445817, 9.920743607148, -75197.512299157, 2970.8605951158, -3.4406878548526, 0.38815564249115, 17511.29508575, -1423.7112854449, 1.0943803364167, 0.89971619308495, -3375.9740098958, 471.62885818355, -1.9188241993679, 0.41078580492196, -0.33465378172097, 1387.0034777505, -406.63326195838, 41.72734715961, 2.1932549434532, -1.0320050009077, 0.35882943516703, 0.0052511453726066, 12.838916450705, -2.8642437219381, 0.56912683664855, -0.099962954584931, -0.0032632037778459, 0.00023320922576723, -0.1533480985745, 0.029072288239902, 0.00037534702741167, 0.0017296691702411, -0.00038556050844504, -0.000035017712292608, -0.000014566393631492, 5.6420857267269E-06, 4.1286150074605E-08, -2.0684671118824E-08, 1.6409393674725E-09],
			pi = P,
			sig = s/0.7853,
			T = 0;

		for(var i = 0; i < 44; i++)
		{
			var N = R2B_PS_N[i],
				I = R2B_PS_I[i],
				J = R2B_PS_J[i];

			T += N*Math.pow(pi,I)*Math.pow(10.0-sig,J);
		}

		return T;
	}

	function r2C_PS_T(P, s)
	{
		var R2C_PS_I = [-2, -2, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 7],
			R2C_PS_J = [0, 1, 0, 0, 1, 2, 3, 0, 1, 3, 4, 0, 1, 2, 0, 1, 5, 0, 1, 4, 0, 1, 2, 0, 1, 0, 1, 3, 4, 5],
			R2C_PS_N = [909.68501005365, 2404.566708842, -591.6232638713, 541.45404128074, -270.98308411192, 979.76525097926, -469.66772959435, 14.399274604723, -19.104204230429, 5.3299167111971, -21.252975375934, -0.3114733441376, 0.60334840894623, -0.042764839702509, 0.0058185597255259, -0.014597008284753, 0.0056631175631027, -0.000076155864584577, 0.00022440342919332, -0.000012561095013413, 6.3323132660934E-07, -2.0541989675375E-06, 3.6405370390082E-08, -2.9759897789215E-09, 1.0136618529763E-08, 5.9925719692351E-12, -2.0677870105164E-11, -2.0874278181886E-11, 1.0162166825089E-10, -1.6429828281347E-10],
			pi = P,
			sig = s/2.9251,
			T = 0;

		for(var i = 0; i < 30; i++)
		{
			var N = R2C_PS_N[i],
				I = R2C_PS_I[i],
				J = R2C_PS_J[i];

			T += N*Math.pow(pi,I)*Math.pow(2.0-sig,J);
		}

		return T;
	}

	//
	//	Backwards equation for region 3 (P and s given)
	//	From : Revised Supplementary Release on Backward Equations for the Functions
	//  T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS Industrial
	//  Formulation 1997 for the Thermodynamic Properties of Water and Steam
	//
	function r3_PS(P, s)
	{
		var T, rho;

		if (s <= NS.CONST('R3_CRT_S'))
		{
			T = r3A_PS_T(P,s);
			rho = r3A_PS_V(P,s);
		}
		else
		{
			T = r3B_PS_T(P,s);
			rho = r3B_PS_V(P,s);
		}

		return PT.r3(P, T, rho);
	}


	function r3A_PS_T(P, s)
	{
		var R3A_I = [-12, -12, -10, -10, -10, -10, -8, -8, -8, -8, -6, -6, -6, -5, -5, -5, -4, -4, -4, -2, -2, -1, -1, 0, 0, 0, 1, 2, 2, 3, 8, 8, 10],
			R3A_J = [28, 32, 4, 10, 12, 14, 5, 7, 8, 28, 2, 6, 32, 0, 14, 32, 6, 10, 36, 1, 4, 1, 6, 0, 1, 4, 0, 0, 3, 2, 0, 1, 2, ],
			R3A_N = [1500420082.63875, -159397258480.424, 5.02181140217975E-4, -67.2057767855466, 1450.58545404456, -8238.8953488889, -0.154852214233853, 11.2305046746695, -29.7000213482822, 43856513263.5495, 0.00137837838635464, -2.97478527157462, 9717779473494.13, -5.71527767052398E-5, 28830.794977842, -74442828926270.3, 12.8017324848921, -368.275545889071, 6647689047791770, 0.044935925195888, -4.22897836099655, -0.240614376434179, -4.74341365254924, 0.72409399912611, 0.923874349695897, 3.99043655281015, 0.0384066651868009, -0.00359344365571848, -0.735196448821653, 0.188367048396131, 0.000141064266818704, -0.00257418501496337, 0.00123220024851555],
			pi = P/100,
			sig = s/4.4,
			T = 0;

		for(var i = 0; i < 33; i++)
		{
			var N = R3A_N[i],
				I = R3A_I[i],
				J = R3A_J[i];

			T += N*Math.pow(pi + 0.24,I)*Math.pow(sig - 0.703, J);
		}

		return 760*T;
	}

	function r3A_PS_V(P, s)
	{
		var R3A_I = [-12, -12, -12, -10, -10, -10, -10, -8, -8, -8, -8, -6, -5, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, 2, 4, 5, 6],
			R3A_J = [10, 12, 14, 4, 8, 10, 20, 5, 6, 14, 16, 28, 1, 5, 2, 4, 3, 8, 1, 2, 0, 1, 3, 0, 0, 2, 2, 0],
			R3A_N = [79.5544074093975, -2382.6124298459, 17681.3100617787, -0.00110524727080379, -15.3213833655326, 297.544599376982, -35031520.6871242, 0.277513761062119, -0.523964271036888, -148011.182995403, 1600148.99374266, 1708023226634.27, 0.000246866996006494, 1.6532608479798, -0.118008384666987, 2.537986423559, 0.965127704669424, -28.2172420532826, 0.203224612353823, 1.10648186063513, 0.52612794845128, 0.277000018736321, 1.08153340501132, -0.0744127885357893, 0.0164094443541384, -0.0680468275301065, 0.025798857610164, -0.000145749861944416],
			pi = P/100,
			sig = s/4.4,
			v = 0;

		for(var i = 0; i < 28; i++)
		{
			var N = R3A_N[i],
				I = R3A_I[i],
				J = R3A_J[i];

			v += N*Math.pow(pi+0.187,I)*Math.pow(sig-0.755,J);
		}

		return 0.0028*v;
	}

	function r3B_PS_T(P, s)
	{
		var R3B_PS_I = [-12, -12, -12, -12, -8, -8, -8, -6, -6, -6, -5, -5, -5, -5, -5, -4, -3, -3, -2, 0, 2, 3, 4, 5, 6, 8, 12, 14],
			R3B_PS_J = [1, 3, 4, 7, 0, 1, 3, 0, 2, 4, 0, 1, 2, 4, 6, 12, 1, 6, 2, 0, 1, 1, 0, 24, 0, 3, 1, 2],
			R3B_PS_N = [0.52711170160166, -40.1317830052742, 153.020073134484, -2247.99398218827, -0.193993484669048, -1.40467557893768, 42.6799878114024, 0.752810643416743, 22.6657238616417, -622.873556909932, -0.660823667935396, 0.841267087271658, -25.3717501764397, 485.708963532948, 880.531517490555, 2650155.92794626, -0.359287150025783, -656.991567673753, 2.41768149185367, 0.856873461222588, 0.655143675313458, -0.213535213206406, 0.00562974957606348, -316955725450471.0, -0.000699997000152457, 0.0119845803210767, 1.93848122022095E-05, -2.15095749182309E-05],
			pi = P/100,
			sig = s/5.3,
			T = 0;

		for(var i = 0; i < 28; i++)
		{
			var N = R3B_PS_N[i],
				I = R3B_PS_I[i],
				J = R3B_PS_J[i];

			T += N*Math.pow(pi+0.76,I)*Math.pow(sig-0.818,J);
		}

		return 860*T;
	}

	function r3B_PS_V(P, s)
	{
		var R3B_PS_v_I = [-12, -12, -12, -12, -12, -12, -10, -10, -10, -10, -8, -5, -5, -5, -4, -4, -4, -4, -3, -2, -2, -2, -2, -2, -2, 0, 0, 0, 1, 1, 2],
			R3B_PS_v_J = [0, 1, 2, 3, 5, 6, 0, 1, 2, 4, 0, 1, 2, 3, 0, 1, 2, 3, 1, 0, 1, 2, 3, 4, 12, 0, 1, 2, 0, 2, 2],
			R3B_PS_v_N = [5.91599780322238E-5, -0.00185465997137856, 0.0104190510480013, 0.0059864730203859, -0.771391189901699, 1.72549765557036, -0.000467076079846526, 0.0134533823384439, -0.0808094336805495, 0.508139374365767, 0.00128584643361683, -1.63899353915435, 5.86938199318063, -2.92466667918613, -0.00614076301499537, 5.76199014049172, -12.1613320606788, 1.67637540957944, -7.44135838773463, 0.0378168091437659, 4.01432203027688, 16.0279837479185, 3.17848779347728, -3.58362310304853, -1159952.60446827, 0.199256573577909, -0.122270624794624, -19.1449143716586, -0.0150448002905284, 14.6407900162154, -3.2747778718823],
			pi = P/100,
			sig = s/5.3,
			v = 0;

		for(var i = 0; i < 31; i++)
		{
			var N = R3B_PS_v_N[i],
				I = R3B_PS_v_I[i],
				J = R3B_PS_v_J[i];

			v += N*Math.pow(pi+0.298, I)*Math.pow(sig-0.816, J);
		}

		return 0.0088*v;
	}

	//
	// Region 4
	//
	function r4_PS(P, s)
	{
		var T = PT.r4_P_Tsat(P);

		return PT.solve(P, T);
	}

	function r4_S_Psat(s)
	{
		var R4_I = [0, 1, 1, 4, 12, 12, 16, 24, 28, 32],
			R4_J = [0, 1, 32, 7, 4, 14, 36, 10, 0, 18],
			R4_N = [0.639767553612785, -1.29727445396014E1, -2.24595125848403E16, 1.77466741801846E6, 7.17079349571538E9, -3.78829107169011E17, -9.55586736431328E34, 1.87269814676188E23, 1.19254746466473E11, 1.10649277244882E36],
			sig = s/5.2,
			p = 0;

		for(var i = 0; i < 10; i++)
		{
			var I = R4_I[i],
				J = R4_J[i],
				N = R4_N[i];

			p += N*Math.pow(sig - 1.03, I)*Math.pow(sig - 0.699, J);
		}

		return 22*p;
	}
}));
